home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / C / Snippets / Draw n Save 1.1 / Draw n Save.c next >
Encoding:
C/C++ Source or Header  |  1995-12-02  |  7.2 KB  |  235 lines  |  [TEXT/CWIE]

  1. /*
  2.     File: Draw n Save.c
  3.  
  4.     Written by: Hiep Dam
  5.                 From The Witches' Brew
  6.                 starlabs@aol.com
  7.  
  8.                 Public domain. Copy, steal, plagiarize mercilessly without
  9.                 fear of persecution. As you do, note that any liabilities
  10.                 are therefore yours to handle. :-)
  11.  
  12.     Date: August 4 1994
  13.     Version:
  14.         1.1 Oct 95
  15.             Added provision for saving a file over another file with the
  16.             same name ("replace file?") and added ostype creator argument
  17.             to savepicture...
  18.  
  19.  
  20.     Purpose: Puts up a window, lets you "draw" into the window (press a key to
  21.              exit) and then lets you save your drawing as a standard PICT file. Voila!
  22.              Mostly for beginners.
  23. */
  24.  
  25. // ---------------------------------------------------------------------------
  26.  
  27. void InitToolboxCrud();
  28. void SavePicture(Handle thePic, OSType creator);
  29.  
  30. // ---------------------------------------------------------------------------
  31.  
  32. void main() {
  33.     WindowPtr canvasWindow;        // This is the window we'll be drawing into
  34.     PicHandle myPic;            // This is the picture we'll stuff our drawing into
  35.     Boolean done = false;        // A flag to tell us when we'll be done
  36.     Rect windR;                    // Rect of the window
  37.     Point mLoc, oldLoc;            // Local mouse coords (for our drawing)
  38.     EventRecord theEvent;        // Used by GetNextEvent, to tell us when to stop drawing
  39.     
  40.     InitToolboxCrud();
  41.     
  42.     /*
  43.         OK, let's setup some stuff before we can do the "cool" stuff:
  44.         1) Setup the window
  45.         2) Setup the graphics environment
  46.     */
  47.     windR = (**GetGrayRgn()).rgnBBox;
  48.     InsetRect(&windR, 50, 50);
  49.     canvasWindow = NewWindow(nil, &windR, "\pCanvas*Press key to end demo.",
  50.         true, documentProc, (WindowPtr)-1, false, 0);
  51.     SetPort(canvasWindow);
  52.  
  53.     // Important to call ClipRect, since upon creation a port's cliprgn's bounds
  54.     // are set wide open (-32,767 to 32,767). Not clipping may result in integer
  55.     // overflow, in which case we might not see a picture at all. In any case
  56.     // a minor but important point.
  57.     ClipRect(&canvasWindow->portRect);
  58.     
  59.     // Tell the Mac OS to begin recording [most] QuickDraw calls from now on,
  60.     // until we call ClosePicture. LineTos, FrameRects, etc. are recorded
  61.     // by the operating system.
  62.     myPic = OpenPicture(&canvasWindow->portRect);
  63.     // By default, calling OpenPicture hides the pen so no drawing is seen.
  64.     // This is contrary to what we want so we'll have to show the pen.
  65.     ShowPen();
  66.     
  67.     // Loop thru and do some fancy-smancy drawing...
  68.     // The code could have been simplified, but this is more efficient
  69.     // in that only changes in the mouse coords are drawn...
  70.     
  71.     // On color macs, we'll draw in blue. Oh joy!
  72.     ForeColor(blueColor);
  73.     do  {
  74.         // Is mouse down? If so, time to start recording/drawing
  75.         // our line(s)...
  76.         if (Button())  {
  77.             GetMouse(&mLoc);
  78.             MoveTo(mLoc.h, mLoc.v);
  79.             oldLoc = mLoc;
  80.  
  81.             while (Button())  {
  82.                 GetMouse(&mLoc);
  83.                 if (oldLoc.h != mLoc.h || oldLoc.v != mLoc.v) {
  84.                     LineTo(mLoc.h, mLoc.v);    // Actual drawing here
  85.                     oldLoc = mLoc;
  86.                 }
  87.             }
  88.         }
  89.  
  90.         // Press a key to finish up drawing
  91.         if (GetNextEvent(keyDownMask, &theEvent))
  92.             done = true;
  93.     } while (!done);
  94.     // Restore the color
  95.     ForeColor(blackColor);
  96.  
  97.     // We're done drawing, stop the recording mechanism
  98.     ClosePicture();
  99.     
  100.     // Just to test if we've done things correctly, tell
  101.     // QuickDraw to redraw what we've just recorded...
  102.     EraseRect(&canvasWindow->portRect);
  103.     DrawPicture(myPic, &(**myPic).picFrame);
  104.     
  105.     // Save our newly created picture!
  106.     SavePicture((Handle)myPic, 'Hiep');
  107.  
  108.     // Remember, if you're going to put this stuff in a "real"
  109.     // application, remember to de-allocate the memory taken
  110.     // up by the picture once you're done...
  111.     // (Since we've created the picture via OpenPicture, we
  112.     // call KillPicture. If instead we've gotten our picture
  113.     // via GetPicture, we should instead call ReleaseResource).
  114.     // But note: if we had saved the picture as a 'PICT'
  115.     // resource, we need to use ReleaseResource....
  116.     KillPicture(myPic);
  117. } // END main
  118.  
  119. // ---------------------------------------------------------------------------
  120.  
  121. /*
  122.     This (handy?) little 'ol function saves a picture as a standard "PICT"
  123.     file. Note that barely any error-checking is done; you should add more
  124.     extensive checking for your own application(s). As an excuse for error
  125.     checking, this routine beeps when it encounters one and exits (quite
  126.     ungracefully, too).
  127.     
  128.     A special note concerning PICT files: A pict file is like any other
  129.     "data" file in that you write stuff to the data fork. However, the
  130.     pict file also contains a "special" 512-byte header. Most of the time
  131.     you can ignore this. So when writing to or reading from a pict file,
  132.     just skip the first 512 bytes (i.e. SetFPos(fileRefNum, fsFromStart, 512))
  133.     and all will be well. My experience is that almost all applications
  134.     ignore this 512-byte header (but keep it due to ancient history).
  135.     
  136.     By the way, the code herein is System 7 dependent. If you wish to
  137.     change to System 6 compatibility, you'll have to change the
  138.     StandardFileReply to an SFReply, etc. etc. etc.
  139.     (But why System 6?)
  140. */
  141.  
  142. void SavePicture(Handle thePic, OSType creator)  {
  143.     StandardFileReply reply;
  144.     OSErr myErr;
  145.     short fileRefNum;
  146.     long picSize;        // The size of our picture, give or take a header
  147.     
  148.     // Put up the standard save dialog
  149.     StandardPutFile("\pSave picture into:", "\pMy picture.pict", &reply);
  150.  
  151.     if (reply.sfGood)  {
  152.         if (reply.sfReplacing) {
  153.             myErr = FSpDelete(&reply.sfFile);
  154.             if (myErr != noErr) {
  155.                 SysBeep(10);
  156.                 return;
  157.             }
  158.         }
  159.  
  160.         // Create the file.
  161.         myErr = FSpCreate(&reply.sfFile, creator, 'PICT', reply.sfScript);
  162.         if (myErr != noErr)  {
  163.             SysBeep(10);
  164.             return;
  165.         }
  166.  
  167.         // Open it up (the data fork, that is)...
  168.         myErr = FSpOpenDF(&reply.sfFile, fsCurPerm, &fileRefNum);
  169.         if (myErr != noErr)  {
  170.             SysBeep(10);
  171.             return;
  172.         }
  173.  
  174.         // Lock up the picture, since it may move when writing to
  175.         // our file. Also get the size of our picture. Then tell
  176.         // the File Manager to allocate enough space in the file
  177.         // for us, keeping in mind the 512-byte header...
  178.         HLock(thePic);
  179.         picSize = GetHandleSize(thePic);
  180.         picSize = picSize + 512;
  181.         myErr = SetEOF(fileRefNum, picSize);
  182.         if (myErr != noErr)  {
  183.             SysBeep(10);
  184.             return;
  185.         }
  186.  
  187.         // Alright, time to do the dirty deed (but first,
  188.         // since we don't want to write in the header, tell
  189.         // the File Manager to skip the first 512-bytes)
  190.         myErr = SetFPos(fileRefNum, fsFromStart, 512);
  191.         if (myErr != noErr)  {
  192.             SysBeep(10);
  193.             return;
  194.         }
  195.  
  196.         // OK, ok, here we are. Write to the file.
  197.         // Note: FSWrite expects a pointer to our data (i.e. the
  198.         // picture). So we'll have to dereference the
  199.         // picture handle.
  200.         picSize = GetHandleSize(thePic);
  201.         myErr = FSWrite(fileRefNum, &picSize, (Ptr)*thePic);
  202.         if (myErr != noErr)  {
  203.             SysBeep(10);
  204.             return;
  205.         }
  206.  
  207.         // Close it up. You may have to call FlushVol() or
  208.         // such to tell the File Manager to write the data
  209.         // to the file immediately (otherwise it waits a
  210.         // while...)
  211.         myErr = FSClose(fileRefNum);
  212.         if (myErr != noErr)  {
  213.             SysBeep(10);
  214.             return;
  215.         }
  216.     }
  217. } // END SavePicture
  218.  
  219. // ---------------------------------------------------------------------------
  220.  
  221. // Hey, why don't they put this crap in automagically, like Think Pascal,
  222. // so us programmers can move on to the more interesting stuff?!?
  223.  
  224. void InitToolboxCrud()  {
  225.     InitGraf((Ptr) &qd.thePort);
  226.     InitFonts();
  227.     InitWindows();
  228.     InitMenus();
  229.     FlushEvents(everyEvent,0);
  230.     TEInit();
  231.     InitDialogs(0L);
  232.     InitCursor();
  233. } // END InitToolboxCrud
  234.  
  235.